/* QtLua -- Lua bindings for Qt
   Copyright (C) 2011, Jarek Pelczar

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 3 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General
   Public License along with this library; if not, write to the
   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
   Boston, MA 02110-1301 USA

*/

#include "qluascriptdebuggerstackmodel_p.h"
#include "qluascriptcontextinfo.h"
#include <QDebug>

class QLuaScriptDebuggerStackModelPrivate
{
public:
    QList<QLuaScriptContextInfo> m_stack;
};

QLuaScriptDebuggerStackModel::QLuaScriptDebuggerStackModel(QObject *parent) :
    QAbstractItemModel(parent)
{
    d = new QLuaScriptDebuggerStackModelPrivate;
}

QLuaScriptDebuggerStackModel::~QLuaScriptDebuggerStackModel()
{
    delete d;
}

QList<QLuaScriptContextInfo> QLuaScriptDebuggerStackModel::callStack() const
{
    return d->m_stack;
}

void QLuaScriptDebuggerStackModel::setCallStack(const QList<QLuaScriptContextInfo>& stack)
{
    beginResetModel();
    d->m_stack = stack;
    endResetModel();
}

void QLuaScriptDebuggerStackModel::pushFrame(const QLuaScriptContextInfo& frame)
{    
#ifdef QT_DEBUG
    qDebug() << "[QLuaScriptDebuggerStackModel] Push frame";
#endif

    beginInsertRows(QModelIndex(), d->m_stack.count(), d->m_stack.count());
    d->m_stack.append(frame);
    endInsertRows();
}

void QLuaScriptDebuggerStackModel::popFrame()
{
#ifdef QT_DEBUG
    qDebug() << "[QLuaScriptDebuggerStackModel] Pop frame";
#endif

    beginRemoveRows(QModelIndex(), d->m_stack.count() - 1, d->m_stack.count() - 1);
    d->m_stack.takeLast();
    endRemoveRows();
}

QModelIndex QLuaScriptDebuggerStackModel::index(int row, int column,
                          const QModelIndex &parent) const
{
    if(parent.isValid())
        return QModelIndex();
    if(row < 0 || row >= d->m_stack.count())
        return QModelIndex();
    if(column < 0 || column >= columnCount())
        return QModelIndex();
    return createIndex(row, column);
}

QModelIndex QLuaScriptDebuggerStackModel::parent(const QModelIndex &child) const
{
    return QModelIndex();
}

int QLuaScriptDebuggerStackModel::rowCount(const QModelIndex &parent) const
{
    if(parent.isValid())
        return 0;
    return d->m_stack.count();
}

int QLuaScriptDebuggerStackModel::columnCount(const QModelIndex &parent) const
{
    if(!parent.isValid())
        return 4;
    return 0;
}

QVariant QLuaScriptDebuggerStackModel::data(const QModelIndex &index, int role) const
{
//#ifdef QT_DEBUG
//    qDebug() << "Row=" << index.row() << "Col=" << index.column() << "role=" << role;
//#endif
    if(!index.isValid() || index.row() >= d->m_stack.count())
        return QVariant();
    if(role == Qt::DisplayRole)
    {
        QLuaScriptContextInfo item = d->m_stack.at(index.row());
        switch(index.column())
        {
        case 0: return item.activationContext();
        case 1: return item.functionName();
        case 2: return item.fileName() + ":" + QString::number(item.lineNumber());
        case 3: {
                switch(item.functionType())
                {
                case QLuaScriptContextInfo::ScriptFunction:
                    return tr("Script");
                case QLuaScriptContextInfo::NativeFunction:
                    return tr("Native");
                case QLuaScriptContextInfo::MainChunk:
                    return tr("Script");
                case QLuaScriptContextInfo::TailCall:
                    return tr("Tail");
                case QLuaScriptContextInfo::QtFunction:
                    return tr("Qt Function");
                case QLuaScriptContextInfo::QtPropertyFunction:
                    return tr("Qt Property");
                default:
                    break;
                }
            }
            break;
        default:
            break;
        }
    }
    return QVariant();
}

QVariant QLuaScriptDebuggerStackModel::headerData(int section, Qt::Orientation orientation,
                            int role) const
{
    if(orientation == Qt::Horizontal && role == Qt::DisplayRole) {
        switch(section) {
        case 0: return tr("Level");
        case 1: return tr("Name");
        case 2: return tr("Location");
        case 3: return tr("Type");
        }
    }
    return QVariant();
}
